package com.activenetwork.listener;

import java.util.ResourceBundle;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.events.AbstractWebDriverEventListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Listener makes WebDriver implicitly wait when
 * <code>WebDriver.findElement(By)</code> and
 * <code>WebDriver.findElements(By)</code> <br/>
 * It will NOT wait when <code>WebElement.findElement(By)</code> and
 * <code>WebElement.findElements(By)</code>
 */
public class ImplicitlyWaitListener extends AbstractWebDriverEventListener {
	Logger logger = LoggerFactory.getLogger(ImplicitlyWaitListener.class);
	
    public static final int DEFAULT_WEBDRIVER_TIME_OUT = 30;
    private int generalWaitSecond;
    private boolean debugMode;
    
    // constructor without general waiting configuration
    public ImplicitlyWaitListener(){
    	try {
    		ResourceBundle bundle = ResourceBundle.getBundle("ImplicitlyWaitListener");
			generalWaitSecond = Integer.valueOf(bundle.getString("second"));
			debugMode = Boolean.valueOf(bundle.getString("debug"));
		} catch (Exception e) {
			generalWaitSecond = 0;
			debugMode = false;
		}
    }
    
    @Override
    public void beforeChangeValueOf(WebElement element, WebDriver driver){
    	generalWait(driver, "beforeChangeValueOf");
    	
    	driver.manage().timeouts().implicitlyWait(
                (element == null ? DEFAULT_WEBDRIVER_TIME_OUT : 0),
                TimeUnit.SECONDS);
    	
    }
    
    @Override
    public void afterChangeValueOf(WebElement element, WebDriver driver){
    	generalWait(driver, "afterChangeValueOf");
    }
    
    @Override
    public void beforeClickOn(WebElement element, WebDriver driver) {
    	generalWait(driver, "beforeClickOn");
    	
    	driver.manage().timeouts().implicitlyWait(
                (element == null ? DEFAULT_WEBDRIVER_TIME_OUT : 0),
                TimeUnit.SECONDS);
    }
    
    @Override
    public void afterClickOn(WebElement element, WebDriver driver){
    	generalWait(driver, "afterClickOn");
    }
    
    @Override
    public void beforeFindBy(By by, WebElement element, WebDriver driver) {
    	generalWait(driver, "beforeFindBy");
    	
        driver.manage().timeouts().implicitlyWait(
                (element == null ? DEFAULT_WEBDRIVER_TIME_OUT : 0),
                TimeUnit.SECONDS);
    }
    
    @Override
    public void afterFindBy(By by, WebElement element, WebDriver driver){
    	generalWait(driver, "afterFindBy");
    }
    
    @Override
    public void beforeNavigateTo(String url, WebDriver driver){
    	generalWait(driver, "beforeNavigateTo");
    }
    
    @Override
    public void afterNavigateTo(String url, WebDriver driver){
    	generalWait(driver, "afterNavigateTo");
    }
    
    /**
     * Deal with general wait
     * @param driver
     * @param methodName
     */
    private void generalWait(WebDriver driver, String methodName){
    	
    	// if process general waiting or not
    	if (generalWaitSecond > 0){
    		driver.manage().timeouts().implicitlyWait(generalWaitSecond, TimeUnit.MILLISECONDS);
    	}
    	
    	// display the message
    	if (debugMode) {
    		logger.info("ImplicitlyWaitListener." + methodName +"() - for general waiting invocation.");
    	}
    }
    
    
}
